package cz.data.domain.market.mapping.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import cz.data.common.annotation.DataInner;
import cz.data.common.base.BaseResponse;
import cz.data.common.base.SimpleDataResponse;
import cz.data.common.exception.DataException;
import cz.data.common.support.db.core.PageResult;
import cz.data.domain.market.mapping.handler.interceptor.DataApiRequestInterceptor;
import cz.data.domain.market.mapping.service.impl.DataApiEngine;
import cz.data.domain.market.model.entity.DataApiEntity;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class DataApiRequestHandler {

    @Resource
    private DataApiRequestInterceptor interceptor;
    @Resource
    private DataApiEngine dataApiEngine;
    @Resource
    private ObjectMapper objectMapper;

    @SneakyThrows
    @ResponseBody
    public Object invoke(HttpServletRequest request, HttpServletResponse response,
                         @PathVariable(required = false) Map<String, Object> pathVariables,
                         @RequestParam(required = false) Map<String, Object> requestParams,
                         @RequestBody(required = false) Map<String, Object> requestBodys) {
        Map<String, Object> params = new HashMap<>();
        if (MapUtils.isNotEmpty(pathVariables)) {
            params.putAll(pathVariables);
        }
        if (MapUtils.isNotEmpty(requestParams)) {
            params.putAll(requestParams);
        }
        if (MapUtils.isNotEmpty(requestBodys)) {
            params.putAll(requestBodys);
        }
        interceptor.authorization(request, DataInner.Access.authenticated.getValue());
        DataApiEntity api = DataApiHandlerMapping.getMappingApiInfo(request);
        long start = System.currentTimeMillis();
        try {
            // 序列化
            api = objectMapper.readValue(objectMapper.writeValueAsString(api), DataApiEntity.class);
            // 执行前置拦截器
            interceptor.preHandle(request, response, api, params);
            PageResult<Map<String, Object>> value = dataApiEngine.execute(api, params);
            // 执行后置拦截器
            interceptor.postHandle(request, response, api, params, value);
            interceptor.postLogHandle(request, api, params, value, null, start);
            return new SimpleDataResponse<Object>(value);
        } catch (Exception e) {
            interceptor.postLogHandle(request, api, params, null, e, start);
            String message = "错误!请稍后重试";
            if (e instanceof DataException) {
                message = e.getMessage();
            }
            log.warn("动态数据接口调用错误: {}", e.getMessage());
            return BaseResponse.error(500, message);
        }
    }
}
